﻿using System.Collections.Generic;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using XNAGame = Microsoft.Xna.Framework.Game;
using FSVector2 = FarseerGames.FarseerPhysics.Mathematics.Vector2;
using CymbergajTouch.Menu;
using CymbergajTouch.Match;

namespace CymbergajTouch.Components
{
    

    /// <summary>
    /// Menu component that manages menu items.
    /// </summary>
    class MenuComponent : DrawableGameComponent
    {
        class MenuMovable : Movable
        {
            private MenuComponent outerObject;
            public MenuMovable(MenuComponent outerObject)
            {
                this.outerObject = outerObject;
            }
            MenuItem touchedMenu(FSVector2 position)
            {
                if (!outerObject.Enabled)
                {
                    return null;
                }
                Vector2 itemPosition = outerObject.menuPosition;
                for (int i = 0; i < outerObject.items.Count; i++)
                {
                    itemPosition.Y += offsetY;
                    SpriteFont menuFont = outerObject.menuFont;
                    Vector2 bounds = menuFont.MeasureString(outerObject.items[i].Name);
                    if (position.X >= itemPosition.X &&
                        position.X <= itemPosition.X + bounds.X &&
                        position.Y >= itemPosition.Y &&
                        position.Y <= itemPosition.Y + bounds.Y)
                    {
                        return outerObject.items[i];
                    }
                    itemPosition.Y += menuFont.LineSpacing;
                }
                return null;
            }

            bool Movable.IsTouched(FSVector2 position)
            {
                return (touchedMenu(position) != null);
            }

            void Movable.Grab(FSVector2 inputPosition)
            {
                touchedMenu(inputPosition).ItemEnter();
            }

            void Movable.Move(FSVector2 newPosition)
            {
                // ignore
            }

            void Movable.Drop()
            {
                // ignore
            }
        }

        private KeyboardInput keyboardInput;
        private MenuMovable menuMovable;
        SpriteFont menuFont;
        List<MenuItem> items = new List<MenuItem>();
        internal Vector2 menuPosition;
        int selectedItem = 0;
        private Texture2D backgroundTexture = null;

        private const int offsetY = 40;

        public MenuComponent(XNAGame game, KeyboardInput keyboardInput)
            : base(game)
        {
            this.keyboardInput = keyboardInput;
            //inputManager.AddMovable
            menuPosition = new Vector2(game.Window.ClientBounds.Width / 4, game.Window.ClientBounds.Height / 4);

            menuMovable = new MenuMovable(this);
            InputManager.Instance.AddMovable(menuMovable);
        }

        protected override void LoadContent()
        {
            menuFont = Game.Content.Load<SpriteFont>("Fonts/scoreFont");
            base.LoadContent();
        }

        public override void Draw(GameTime gameTime)
        {
            SpriteBatch spriteBatch = ((Cymbergaj)Game).SpriteBatch;
            spriteBatch.Begin();
            Vector2 itemPosition = menuPosition;

            if (backgroundTexture != null)
            {
                Rectangle destinationRectangle = new Rectangle((int)(menuPosition.X / 2), (int)(menuPosition.Y / 2), (int)(Game.Window.ClientBounds.Width - menuPosition.X), (int)(Game.Window.ClientBounds.Height - menuPosition.Y));
                spriteBatch.Draw(backgroundTexture, destinationRectangle, null, new Color(Color.CornflowerBlue, 160));
            }

            for (int i = 0; i < items.Count; i++)
            {
                Color color;
                if (i == selectedItem)
                {
                    color = Color.White;
                }
                else
                {
                    color = Color.Black;
                }
                itemPosition.Y += offsetY;
                spriteBatch.DrawString(menuFont, items[i].Name, itemPosition, color);
                itemPosition.Y += menuFont.LineSpacing;
            }
            spriteBatch.End();
            base.Draw(gameTime);
        }

        public override void Update(GameTime gameTime)
        {
            if (keyboardInput.IsNewKeyPressed(Keys.Up))
            {
                MenuUp();
            }
            else if (keyboardInput.IsNewKeyPressed(Keys.Down))
            {
                MenuDown();
            }
            else if (keyboardInput.IsNewKeyPressed(Keys.Enter))
            {
                MenuEnter();
            }

            base.Update(gameTime);
        }

        /// <summary>
        /// Adds menu item.
        /// </summary>
        /// <param name="item">menu item</param>
        public void AddItem(MenuItem item)
        {
            items.Add(item);
        }

        public bool Enabled
        {
            set; get;
        }

        /// <summary>
        /// Sets background of menu.
        /// </summary>
        /// <param name="backgroundTexture">background texture</param>
        public void SetBackgroundTexture(Texture2D backgroundTexture)
        {
            this.backgroundTexture = backgroundTexture;
        }

        /// <summary>
        /// Method for going up in menu.
        /// </summary>
        private void MenuUp()
        {
            selectedItem = (selectedItem - 1 + items.Count) % items.Count;
        }

        /// <summary>
        /// Method for going down in menu.
        /// </summary>
        private void MenuDown()
        {
            selectedItem = (selectedItem + 1) % items.Count;
        }

        /// <summary>
        /// Method for entering menu item.
        /// </summary>
        private void MenuEnter()
        {
            items[selectedItem].ItemEnter();
        }
    }
}
